using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MauiBuilder.Services;
using System.Collections.ObjectModel;

namespace MauiBuilder.ViewModels
{
    /// <summary>
    /// Socket连接日志消息类型
    /// 用于区分不同级别的日志信息，便于界面显示和问题排查
    /// </summary>
    public enum SocketLogType
    {
        /// <summary>信息类型 - 一般状态信息</summary>
        Info,       
        /// <summary>成功类型 - 操作成功信息</summary>
        Success,    
        /// <summary>警告类型 - 需要注意的情况</summary>
        Warning,    
        /// <summary>错误类型 - 操作失败或异常</summary>
        Error       
    }

    /// <summary>
    /// Socket日志消息模型
    /// 用于封装单条Socket操作日志，包含时间、类型、内容等信息
    /// 实现ObservableObject支持数据绑定和实时更新
    /// </summary>
    public partial class SocketLogMessage : ObservableObject
    {
        /// <summary>
        /// 日志唯一标识符
        /// 用于区分不同的日志条目
        /// </summary>
        [ObservableProperty]
        private string _id = Guid.NewGuid().ToString();

        /// <summary>
        /// 日志记录时间
        /// 记录消息发生的精确时间
        /// </summary>
        [ObservableProperty]
        private DateTime _time = DateTime.Now;

        /// <summary>
        /// 日志消息类型
        /// 用于确定显示风格和优先级
        /// </summary>
        [ObservableProperty]
        private SocketLogType _type = SocketLogType.Info;

        /// <summary>
        /// 日志消息内容
        /// 实际的日志文本信息
        /// </summary>
        [ObservableProperty]
        private string _message = string.Empty;

        /// <summary>
        /// 格式化的时间文本
        /// 以HH:mm:ss.fff格式显示，包含毫秒精度
        /// </summary>
        public string TimeText => Time.ToString("HH:mm:ss.fff");

        /// <summary>
        /// 消息类型图标
        /// 根据消息类型返回对应的Emoji图标
        /// </summary>
        public string TypeIcon => Type switch
        {
            SocketLogType.Success => "✅",  // 成功 - 绿色勾
            SocketLogType.Warning => "⚠️",  // 警告 - 黄色三角
            SocketLogType.Error => "❌",     // 错误 - 红色X
            _ => "ℹ️"                      // 信息 - 蓝色i
        };

        /// <summary>
        /// 消息类型颜色
        /// 根据消息类型返回对应的显示颜色
        /// </summary>
        public Color TypeColor => Type switch
        {
            SocketLogType.Success => Colors.Green,  // 成功 - 绿色
            SocketLogType.Warning => Colors.Orange, // 警告 - 橙色
            SocketLogType.Error => Colors.Red,      // 错误 - 红色
            _ => Colors.Blue                        // 信息 - 蓝色
        };
    }

    /// <summary>
    /// Socket管理页面的视图模型
    /// 实现Socket连接管理、消息收发和状态监控
    /// 使用原生.NET TcpClient实现，支持重连机制和日志记录
    /// 实现ISocketStateCallback接口进行状态回调处理
    /// </summary>
    public partial class SocketViewModel : BaseViewModel, ISocketStateCallback
    {
        /// <summary>
        /// Socket管理器实例
        /// 负责实际的TCP连接管理和数据传输
        /// </summary>
        private readonly SocketManager _socketManager;
        
        /// <summary>
        /// 日志管理器实例
        /// 用于记录系统日志信息
        /// </summary>
        private readonly LogManager _logManager = LogManager.Instance;
        
        /// <summary>
        /// 连接时长计时器
        /// 每秒更新一次连接时长显示
        /// </summary>
        private System.Timers.Timer _connectionTimer;

        /// <summary>
        /// Socket连接状态
        /// 标识当前是否已成功连接到服务器
        /// </summary>
        [ObservableProperty]
        private bool _isConnected = false;

        /// <summary>
        /// 服务器地址
        /// TCP连接的目标服务器IP地址或域名
        /// </summary>
        [ObservableProperty]
        private string _serverAddress = "192.168.0.116";

        /// <summary>
        /// 服务器端口
        /// TCP连接的目标端口号
        /// </summary>
        [ObservableProperty]
        private int _serverPort = 1605;

        /// <summary>
        /// 待发送的消息内容
        /// 用户在界面输入的消息文本
        /// </summary>
        [ObservableProperty]
        private string _messageToSend = string.Empty;

        /// <summary>
        /// 连接状态标识
        /// 标识当前是否正在进行连接操作
        /// </summary>
        [ObservableProperty]
        private bool _isConnecting = false;

        /// <summary>
        /// 日志消息集合
        /// 存储所有Socket操作的日志记录，支持界面绑定
        /// </summary>
        [ObservableProperty]
        private ObservableCollection<SocketLogMessage> _logMessages = new();

        /// <summary>
        /// 连接状态文本
        /// 显示在界面上的连接状态描述
        /// </summary>
        [ObservableProperty]
        private string _connectionStatusText = "未连接";

        /// <summary>
        /// 上次连接时间
        /// 记录成功建立连接的时间，用于计算连接时长
        /// </summary>
        [ObservableProperty]
        private DateTime _lastConnectTime = DateTime.MinValue;

        /// <summary>
        /// 已发送消息数量
        /// 统计成功发送的消息总数
        /// </summary>
        [ObservableProperty]
        private int _messagesSent = 0;

        /// <summary>
        /// 已接收消息数量
        /// 统计成功接收的消息总数
        /// </summary>
        [ObservableProperty]
        private int _messagesReceived = 0;

        /// <summary>
        /// 构造函数，初始化Socket视图模型
        /// 配置默认Socket参数、初始化管理器和定时器
        /// 根据Maui交互调试规范，添加详细的初始化日志记录
        /// </summary>
        public SocketViewModel()
        {
            // 创建默认Socket配置（初始配置，连接时会动态更新）
            var defaultConfig = new SocketConfig
            {
                ServerAddress = ServerAddress,
                ServerPort = ServerPort,
                ConnectTimeoutMs = 5000,
                ReceiveTimeoutMs = 30000,
                MaxReconnectAttempts = 3,
                ReconnectDelayMs = 2000
            };

            _socketManager = new SocketManager(defaultConfig);
            _socketManager.SetCallback(this);

            // 初始化连接时长定时器
            _connectionTimer = new System.Timers.Timer(1000); // 每秒更新一次
            _connectionTimer.Elapsed += (sender, e) => 
            {
                if (IsConnected)
                {
                    MainThread.BeginInvokeOnMainThread(() => 
                    {
                        OnPropertyChanged(nameof(ConnectionDurationText));
                    });
                }
            };

            _logManager.LogInfo("SocketViewModel 初始化完成（使用原生TcpClient）");
            AddLogMessage(SocketLogType.Info, "原生Socket管理器已初始化");
        }

        #region 计算属性

        /// <summary>
        /// 连接按钮文本
        /// 根据当前连接状态动态显示按钮文本
        /// 连接中显示"连接中..."，已连接显示"断开连接"，未连接显示"连接服务器"
        /// </summary>
        public string ConnectButtonText => IsConnecting ? "连接中..." : (IsConnected ? "断开连接" : "连接服务器");

        /// <summary>
        /// 连接按钮是否可用
        /// 在连接过程中禁用按钮，防止重复操作
        /// </summary>
        public bool IsConnectButtonEnabled => !IsConnecting;

        /// <summary>
        /// 发送按钮是否可用
        /// 只有在已连接且消息内容不为空时才能发送
        /// </summary>
        public bool IsSendButtonEnabled => IsConnected && !string.IsNullOrWhiteSpace(MessageToSend);

        /// <summary>
        /// 连接状态颜色
        /// 已连接显示绿色，未连接显示红色，提供直观的视觉反馈
        /// </summary>
        public Color ConnectionStatusColor => IsConnected ? Colors.Green : Colors.Red;

        /// <summary>
        /// 连接时长文本
        /// 显示当前连接的持续时间，格式为HH:MM:SS
        /// 未连接时显示"未连接"
        /// </summary>
        public string ConnectionDurationText
        {
            get
            {
                if (!IsConnected || LastConnectTime == DateTime.MinValue)
                    return "未连接";

                var duration = DateTime.Now - LastConnectTime;
                return $"已连接: {duration.Hours:D2}:{duration.Minutes:D2}:{duration.Seconds:D2}";
            }
        }

        /// <summary>
        /// 统计信息文本
        /// 显示发送和接收的消息数量统计
        /// 格式："发送: X | 接收: Y"
        /// </summary>
        public string StatisticsText => $"发送: {MessagesSent} | 接收: {MessagesReceived}";

        #endregion

        #region 命令

        /// <summary>
        /// 连接/断开连接命令
        /// 根据当前连接状态执行相应操作：已连接时断开连接，未连接时建立连接
        /// 根据Maui交互调试规范，包含详细的日志记录和异常处理
        /// </summary>
        [RelayCommand]
        private async Task OnToggleConnection()
        {
            try
            {
                if (IsConnected)
                {
                    // 断开连接
                    _socketManager.Disconnect();
                    AddLogMessage(SocketLogType.Info, "用户手动断开连接");
                }
                else
                {
                    // 连接服务器
                    IsConnecting = true;
                    OnPropertyChanged(nameof(ConnectButtonText));
                    OnPropertyChanged(nameof(IsConnectButtonEnabled));

                    // 更新Socket配置以确保使用最新的服务器地址和端口
                    var currentConfig = new SocketConfig
                    {
                        ServerAddress = ServerAddress,
                        ServerPort = ServerPort,
                        ConnectTimeoutMs = 5000,
                        ReceiveTimeoutMs = 30000,
                        MaxReconnectAttempts = 3,
                        ReconnectDelayMs = 2000
                    };
                    _socketManager.UpdateConfig(currentConfig);

                    AddLogMessage(SocketLogType.Info, $"开始连接到 {ServerAddress}:{ServerPort}");

                    bool success = await _socketManager.ConnectAsync();
                    
                    // 更新UI状态
                    IsConnecting = false;
                    OnPropertyChanged(nameof(ConnectButtonText));
                    OnPropertyChanged(nameof(IsConnectButtonEnabled));
                    
                    if (success)
                    {
                        AddLogMessage(SocketLogType.Success, "连接成功建立");
                    }
                    else
                    {
                        AddLogMessage(SocketLogType.Error, "连接失败");
                    }
                }
            }
            catch (Exception ex)
            {
                _logManager.LogError($"连接操作失败: {ex.Message}");
                AddLogMessage(SocketLogType.Error, $"连接操作异常: {ex.Message}");
                // 确保在异常情况下也能更新UI状态
                IsConnecting = false;
                OnPropertyChanged(nameof(ConnectButtonText));
                OnPropertyChanged(nameof(IsConnectButtonEnabled));
            }
        }

        /// <summary>
        /// 发送消息命令
        /// 向已连接的服务器发送文本消息
        /// 包含输入验证、发送操作、结果反馈和错误处理
        /// 按照Maui交互调试规范记录详细日志
        /// </summary>
        [RelayCommand]
        private async Task OnSendMessage()
        {
            try
            {
                if (!IsConnected)
                {
                    AddLogMessage(SocketLogType.Warning, "未连接到服务器，无法发送消息");
                    return;
                }

                if (string.IsNullOrWhiteSpace(MessageToSend))
                {
                    AddLogMessage(SocketLogType.Warning, "消息内容不能为空");
                    return;
                }

                string message = MessageToSend.Trim();
                bool success = await _socketManager.SendMessageAsync(message);

                if (success)
                {
                    MessagesSent++;
                    AddLogMessage(SocketLogType.Success, $"发送消息: {message}");
                    
                    // 清空输入框
                    MessageToSend = string.Empty;
                }
                else
                {
                    AddLogMessage(SocketLogType.Error, "消息发送失败");
                }
            }
            catch (Exception ex)
            {
                _logManager.LogError($"发送消息失败: {ex.Message}");
                AddLogMessage(SocketLogType.Error, $"发送消息异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 清空日志命令
        /// 清除所有显示在界面上的日志记录
        /// 执行后会添加一条新的提示日志
        /// </summary>
        [RelayCommand]
        private void OnClearLogs()
        {
            LogMessages.Clear();
            AddLogMessage(SocketLogType.Info, "日志已清空");
            _logManager.LogInfo("用户清空了Socket日志");
        }

        /// <summary>
        /// 测试连接命令
        /// 使用单独的TcpClient测试到目标服务器的连接性
        /// 不影响当前的正式连接，仅用于网络可达性检查
        /// 设目3秒超时，返回详细的测试结果
        /// </summary>
        [RelayCommand]
        private async Task OnTestConnection()
        {
            try
            {
                // 使用当前页面的服务器地址和端口进行测试
                AddLogMessage(SocketLogType.Info, $"测试连接到 {ServerAddress}:{ServerPort}");
                
                using var testClient = new System.Net.Sockets.TcpClient();
                var connectTask = testClient.ConnectAsync(ServerAddress, ServerPort);
                var timeoutTask = Task.Delay(3000); // 3秒超时

                if (await Task.WhenAny(connectTask, timeoutTask) == timeoutTask)
                {
                    AddLogMessage(SocketLogType.Error, "连接测试超时");
                }
                else if (testClient.Connected)
                {
                    AddLogMessage(SocketLogType.Success, "连接测试成功，服务器可达");
                    testClient.Close();
                }
                else
                {
                    AddLogMessage(SocketLogType.Error, "连接测试失败");
                }
            }
            catch (Exception ex)
            {
                AddLogMessage(SocketLogType.Error, $"连接测试异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 发送心跳命令
        /// 向服务器发送心跳包(HEARTBEAT)保持连接活跃
        /// 只有在已连接状态下才能执行，否则显示警告信息
        /// </summary>
        [RelayCommand]
        private async Task OnSendHeartbeat()
        {
            if (IsConnected)
            {
                await _socketManager.SendMessageAsync("HEARTBEAT");
                AddLogMessage(SocketLogType.Info, "发送心跳包");
            }
            else
            {
                AddLogMessage(SocketLogType.Warning, "未连接，无法发送心跳");
            }
        }

        #endregion

        #region ISocketStateCallback 实现

        /// <summary>
        /// Socket连接状态变化回调
        /// 当Socket连接成功或断开时由SocketManager调用
        /// 更新UI状态并记录连接时间，确保在主线程中执行
        /// </summary>
        /// <param name="isConnected">是否已连接</param>
        public void OnSocketStateChanged(bool isConnected)
        {
            MainThread.BeginInvokeOnMainThread(() =>
            {
                IsConnected = isConnected;
                ConnectionStatusText = isConnected ? "已连接" : "未连接";
                
                if (isConnected)
                {
                    LastConnectTime = DateTime.Now;
                }

                _logManager.LogInfo($"Socket连接状态变化: {(isConnected ? "已连接" : "已断开")}");
            });
        }

        /// <summary>
        /// Socket消息接收回调
        /// 当从服务器接收到数据时由SocketManager调用
        /// 根据消息内容类型进行分类处理和统计，确保在主线程中执行
        /// </summary>
        /// <param name="message">接收到的消息</param>
        public void OnSocketMessageReceived(string message)
        {
            MainThread.BeginInvokeOnMainThread(() =>
            {
                if (message.StartsWith("接收到的数据=") || message.StartsWith("收到服务器消息:"))
                {
                    MessagesReceived++;
                    AddLogMessage(SocketLogType.Success, message);
                }
                else
                {
                    AddLogMessage(SocketLogType.Info, message);
                }
            });
        }

        /// <summary>
        /// Socket错误回调
        /// 当Socket操作发生错误时由SocketManager调用
        /// 记录错误日志并显示给用户，确保在主线程中执行
        /// </summary>
        /// <param name="error">错误信息</param>
        public void OnSocketError(string error)
        {
            MainThread.BeginInvokeOnMainThread(() =>
            {
                AddLogMessage(SocketLogType.Error, error);
                _logManager.LogError($"Socket错误: {error}");
            });
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 添加日志消息
        /// 创建新的日志条目并添加到集合中，自动维护日志数量上限
        /// 新消息插入到列表顶部，超过100条时删除旧记录
        /// </summary>
        /// <param name="type">消息类型</param>
        /// <param name="message">消息内容</param>
        private void AddLogMessage(SocketLogType type, string message)
        {
            var logMessage = new SocketLogMessage
            {
                Type = type,
                Message = message,
                Time = DateTime.Now
            };

            LogMessages.Insert(0, logMessage);

            // 限制日志数量
            while (LogMessages.Count > 100)
            {
                LogMessages.RemoveAt(LogMessages.Count - 1);
            }
        }

        #endregion

        #region 资源释放

        /// <summary>
        /// 页面消失时的清理
        /// 可以选择断开连接或保持连接（当前配置为保持连接）
        /// 用于页面生命周期管理
        /// </summary>
        public void OnDisappearing()
        {
            // 可以选择断开连接或保持连接
            // _socketManager?.Disconnect();
        }

        /// <summary>
        /// 释放资源
        /// 停止并释放定时器和Socket管理器资源
        /// 防止内存泄漏和资源占用
        /// </summary>
        public void Dispose()
        {
            _connectionTimer?.Stop();
            _connectionTimer?.Dispose();
            _socketManager?.Dispose();
        }

        #endregion

        #region 属性变化处理

        /// <summary>
        /// 当MessageToSend属性变化时，同步更新IsSendButtonEnabled属性
        /// 确保发送按钮的可用状态与UI输入内容保持同步
        /// </summary>
        /// <param name="value">新的消息内容</param>
        partial void OnMessageToSendChanged(string value)
        {
            OnPropertyChanged(nameof(IsSendButtonEnabled));
        }

        /// <summary>
        /// 当IsConnected属性变化时，同步更新相关的计算属性
        /// 自动更新按钮文本、状态颜色、连接时长等UI元素
        /// 根据连接状态控制定时器的启停
        /// </summary>
        /// <param name="value">连接状态</param>
        partial void OnIsConnectedChanged(bool value)
        {
            OnPropertyChanged(nameof(ConnectButtonText));
            OnPropertyChanged(nameof(IsSendButtonEnabled));
            OnPropertyChanged(nameof(ConnectionStatusColor));
            OnPropertyChanged(nameof(ConnectionDurationText));
                
            // 根据连接状态控制定时器
            if (value)
            {
                _connectionTimer?.Start();
            }
            else
            {
                _connectionTimer?.Stop();
            }
        }

        /// <summary>
        /// 当IsConnecting属性变化时，同步更新相关的计算属性
        /// 在连接过程中禁用连接按钮，防止重复操作
        /// </summary>
        /// <param name="value">是否正在连接</param>
        partial void OnIsConnectingChanged(bool value)
        {
            OnPropertyChanged(nameof(ConnectButtonText));
            OnPropertyChanged(nameof(IsConnectButtonEnabled));
        }

        /// <summary>
        /// 当MessagesSent属性变化时，更新统计信息
        /// 保持发送消息数量统计的实时性
        /// </summary>
        /// <param name="value">发送消息数</param>
        partial void OnMessagesSentChanged(int value)
        {
            OnPropertyChanged(nameof(StatisticsText));
        }

        /// <summary>
        /// 当MessagesReceived属性变化时，更新统计信息
        /// 保持接收消息数量统计的实时性
        /// </summary>
        /// <param name="value">接收消息数</param>
        partial void OnMessagesReceivedChanged(int value)
        {
            OnPropertyChanged(nameof(StatisticsText));
        }
        
        /// <summary>
        /// 当ServerAddress属性变化时，提示用户重新连接
        /// 在已连接状态下修改服务器地址时给出警告提示
        /// </summary>
        /// <param name="value">新的服务器地址</param>
        partial void OnServerAddressChanged(string value)
        {
            if (IsConnected)
            {
                AddLogMessage(SocketLogType.Warning, $"服务器地址已更改为 {value}，需要重新连接以生效");
            }
        }
        
        /// <summary>
        /// 当ServerPort属性变化时，提示用户重新连接
        /// 在已连接状态下修改服务器端口时给出警告提示
        /// </summary>
        /// <param name="value">新的服务器端口</param>
        partial void OnServerPortChanged(int value)
        {
            if (IsConnected)
            {
                AddLogMessage(SocketLogType.Warning, $"服务器端口已更改为 {value}，需要重新连接以生效");
            }
        }

        #endregion
    }
}